# -*- coding: utf-8 -*-
"""
硬件原始 payload → 内部 TelemetryRow 列表 + QualityEvent
"""
from __future__ import annotations

import json
import re
import time
from datetime import datetime, timezone, timedelta
from decimal import Decimal
from typing import List

from common.base_enums import MeterType, MeterPhase
from common.config import settings
from common.database import DatabaseManager
from common.exceptions import BizException, ErrorCode
from common.logger import create_logger
from mqtt.consumer.event_models import QualityEvent
from mqtt.consumer.mqtt_models import TelemetryRow
from mqtt.consumer.rule_engine import RuleEngine

logger = create_logger("transformer", settings.log_level, settings.log_file)


class TransformError(RuntimeError):
	"""转换层统一异常"""


_rule_engine: RuleEngine | None = None


def get_rule_engine(db: DatabaseManager) -> RuleEngine:
	global _rule_engine
	if _rule_engine is None:
		_rule_engine = RuleEngine(db)
	return _rule_engine


def process(raw_payload: bytes, topic: str, db: DatabaseManager) -> tuple[List[TelemetryRow], QualityEvent]:
	"""入口：返回 (rows, event)"""
	try:
		payload_str = raw_payload.decode()
		# 尝试直接解析
		payload = json.loads(payload_str)
	except UnicodeDecodeError as e:
		logger.error(f"[JSON解析] 字符编码失败 topic={topic}: {e}")
		raise TransformError(f"字符编码失败: {e}")
	except json.JSONDecodeError as e:
		logger.warning(f"[JSON解析] 格式错误，尝试修复: {e}")
		# 尝试修复常见的JSON格式问题
		try:
			fixed_payload_str = _fix_json_format(payload_str)
			payload = json.loads(fixed_payload_str)
			logger.info(f"[JSON解析] 修复成功 topic={topic}")
		except Exception as fix_error:
			logger.error(f"[JSON解析] 修复失败 topic={topic}: {fix_error}")
			logger.error(f"[JSON解析] 原始内容: {payload_str[:500]}...")
			raise TransformError(f"JSON 解析失败: {e}")
	except Exception as e:
		logger.error(f"[JSON解析] 未知错误 topic={topic}: {e}")
		raise TransformError(f"JSON 解析失败: {e}")

	# --- 1. topic 降级解析 ---
	try:
		_, _, topic_id, _ = topic.split("/", 3)
	except ValueError:
		raise TransformError(f"topic 格式错误: {topic}")

	# --- 2. 取 meter_code ---
	if "meters" in payload:  # 单相
		meters: dict = payload["meters"]
		if not meters:
			raise TransformError("meters 字段为空")
		real_meter_code = next(iter(meters.keys()))
	elif "ID" in payload:  # 三相
		real_meter_code = payload["ID"]
	else:
		real_meter_code = topic_id

	# --- 3. 时间 / msg_id ---
	ts_ms = int(payload.get("ts", time.time() * 1000))
	msg_id = payload.get("msg_id") or f"{real_meter_code}_{ts_ms}"
	ts_utc = datetime.fromtimestamp(ts_ms / 1000, tz=timezone.utc)
	cn_tz = timezone(timedelta(hours=8))
	ts = ts_utc.astimezone(cn_tz)

	# --- 4. 转换 ---
	if "a_v" in payload:
		rows = _convert_three_phase(msg_id, real_meter_code, ts, payload)
	elif "meters" in payload:
		rows = _convert_single_phase(msg_id, real_meter_code, ts, payload)
	else:
		raise BizException.from_error_code(ErrorCode.CONFLICT)

	# --- 5. 计算 quality ---
	engine = get_rule_engine(db)
	quality = "BAD" if engine.any_hit(rows[0]) else "GOOD"

	for r in rows:
		r.quality = quality

	event = QualityEvent(
		msg_id=msg_id,
		meter_code=real_meter_code,
		meter_type=MeterType.THREE_PHASE.value if len(rows) > 1 else MeterType.SINGLE.value,
		phase=rows[0].phase.value,
		ts=ts,
		quality=quality,
		voltage=rows[0].voltage,
		current=rows[0].current,
		watt=rows[0].watt,
		temperature1=rows[0].temperature1,
		temperature2=rows[0].temperature2,
		raw_snapshot=rows[0].raw_snapshot,
	)
	return rows, event


# ---------------- 私有 ----------------
def _fix_json_format(json_str: str) -> str:
	"""修复常见的JSON格式问题"""
	# 1. 修复数字前导零问题（如 01 -> 1）
	# 匹配数字前导零的模式：": 0\d+"
	json_str = re.sub(r'(:\s*)0(\d+)', r'\1\2', json_str)

	# 2. 其他常见修复可以在这里添加
	# 例如：修复缺少逗号的问题

	return json_str


def _convert_three_phase(msg_id: str, meter_code: str, ts: datetime, p: dict) -> List[TelemetryRow]:
	ext = {k: p[k] for k in ("hr", "total_energy", "total_power", "T3") if k in p}
	rows = []
	for phase, ph_key in (("A", "a"), ("B", "b"), ("C", "c")):
		rows.append(
			TelemetryRow(
				msg_id=msg_id,
				meter_code=meter_code,
				phase=MeterPhase[phase],
				meter_type=MeterType.THREE_PHASE,
				ts=ts,
				voltage=Decimal(str(p[f"{ph_key}_v"])),
				current=Decimal(str(p[f"{ph_key}_c"])),
				watt=Decimal(str(p[f"{ph_key}_p"])),
				total_kwh=Decimal(str(p["total_energy"])),
				temperature1=Decimal(str(p.get("T1", 0))),
				temperature2=Decimal(str(p.get("T2", 0))),
				ext_json=ext,
				raw_snapshot=p,
			)
		)
	logger.debug("三相转换完成 msg_id=%s rows=%d", msg_id, len(rows))
	return rows


def _convert_single_phase(msg_id: str, meter_code: str, ts: datetime, p: dict) -> List[TelemetryRow]:
	meters = p.get("meters")
	if not meters or not isinstance(meters, dict):
		raise TransformError("meters 字段为空或类型错误")

	device_id, readings = next(iter(meters.items()))
	if isinstance(readings, list) and readings:
		readings = readings[0]
	if not isinstance(readings, dict):
		raise TransformError("meters 内无有效字典")

	# 修复：为单相电表保留完整的原始消息结构，同时在readings中添加设备ID
	# 这样既保持了原始消息的完整性，又确保HR字段在合适的位置
	enhanced_readings = readings.copy()
	enhanced_readings["device_id"] = device_id

	ext = {"HR": readings.get("HR"), "device_id": device_id}
	return [
		TelemetryRow(
			msg_id=msg_id,
			meter_code=meter_code,
			phase=MeterPhase.A,
			meter_type=MeterType.SINGLE,
			ts=ts,
			voltage=Decimal(str(readings["V"])),
			current=Decimal(str(readings["C"])),
			watt=Decimal(str(readings["W"])),
			total_kwh=Decimal(str(readings.get("TW", 0))),
			temperature1=Decimal(str(readings.get("T1", 0))),
			temperature2=Decimal(str(readings.get("T2", 0))),
			ext_json=ext,
			raw_snapshot=enhanced_readings,  # 使用增强的readings，包含device_id
		)
	]
